/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.fresh.bus.canoe.amf;

import com.fresh.bus.canoe.exception.ServerException;
import com.fresh.bus.canoe.message.Message;
import com.fresh.bus.canoe.message.Request;
import com.fresh.bus.canoe.message.Response;
import com.fresh.bus.canoe.message.support.AbstractMessageCodec;
import com.exadel.flamingo.flex.messaging.amf.io.AMF3Deserializer;
import com.exadel.flamingo.flex.messaging.amf.io.AMF3Serializer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author dingdang
 */
public class AMFMessageCodec extends AbstractMessageCodec{
    private static Logger log = LoggerFactory.getLogger(AMFMessageCodec.class);

    public AMFMessageCodec()
    {
        super();
    }

     @Override
    public Request decodeRequest(byte[] bytes) throws ServerException {
        Request request = new Request();

        decodeMessage(bytes, request);

        return request;
    }

    @Override
    protected byte[] doEncodeResponse(Response response) throws ServerException {
        if (response == null) {
            return null;
        }

        return encodeMessage(response);
    }

    protected byte[] encodeMessage(Message message)
    {
        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        AMF3Serializer out = new AMF3Serializer(bytesOut);

        try
        {
            out.writeShort(message.getOpcode());
            if(message.getData() != null)
            {
                out.writeObject(message.getData());
            }

            out.flush();
            bytesOut.flush();
            return bytesOut.toByteArray();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return null;
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            try {
                bytesOut.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    protected void decodeMessage(byte[] bytes, Message message)
    {
        AMF3Deserializer in = new AMF3Deserializer(new ByteArrayInputStream(bytes));
        short opcode;

        try {
            try {
                opcode = in.readShort();
                message.setOpcode(opcode);
                if(in.available() != 0)
                {
                    message.setData(in.readObject());
                }
            } catch (IOException ex) {
                throw new ServerException(ServerException.REQUEST_READ_ERROR, ex);
            }
        } finally {
            try {
                in.close();
            } catch (IOException ex) {
                log.error(ex.getMessage(), ex);
            }
        }
    }
}
